package com.codeoss.module.sale.service.impl;

import java.math.BigDecimal;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.codeoss.framework.service.impl.BaseService;
import com.codeoss.framework.util.DateUtil;
import com.codeoss.module.account.model.AccountTax;
import com.codeoss.module.account.service.IAccountTaxService;
import com.codeoss.module.ir.service.IIrDocTypeService;
import com.codeoss.module.ir.service.IIrSequenceService;
import com.codeoss.module.sale.dao.SaleOrderMapper;
import com.codeoss.module.sale.model.SaleOrder;
import com.codeoss.module.sale.model.SaleOrderLine;
import com.codeoss.module.sale.model.SaleQuotation;
import com.codeoss.module.sale.model.SaleQuotationLine;
import com.codeoss.module.sale.service.ISaleOrderLineService;
import com.codeoss.module.sale.service.ISaleOrderService;
import com.codeoss.module.sale.service.ISaleQuotationLineService;
import com.codeoss.module.sale.service.ISaleQuotationService;
import com.codeoss.module.stock.model.StockLocator;
import com.codeoss.module.stock.service.IStockLocatorService;
import com.codeoss.module.stock.service.IStockStorageService;

@Service
public class SaleOrderService extends BaseService<SaleOrderMapper, SaleOrder> implements ISaleOrderService {
	@Autowired
	private ISaleOrderLineService saleOrderLineService;
	@Autowired
	private IAccountTaxService accountTaxService;
	@Autowired
	private ISaleQuotationService saleQuotationService;
	@Autowired
	private ISaleQuotationLineService saleQuotationLineService;
	@Autowired
	private IIrDocTypeService irDocTypeService;
	@Autowired
	private DateUtil dateUtil;
	@Autowired
	private IIrSequenceService irSequenceService;
	@Autowired
	private IStockLocatorService stockLocatorService;
	@Autowired
	private IStockStorageService stockStorageService;
	@Override
	public BigDecimal calculateAmountTotal(Long id) {
		// TODO Auto-generated method stub
		QueryWrapper<SaleOrderLine> lineQuery = new QueryWrapper<SaleOrderLine>();
		lineQuery.eq("sale_order_id", id);
		List<SaleOrderLine> lineList = saleOrderLineService.list(lineQuery);
		BigDecimal amountTotal = new BigDecimal(0);
		for (SaleOrderLine line : lineList) {
			BigDecimal subTotal = line.getAmountSubtotal();
			if (subTotal != null) {
				amountTotal = amountTotal.add(subTotal);
			}
		}
		return amountTotal;
	}

	@Override
	public BigDecimal calculateAmountUntaxed(Long id) {
		// TODO Auto-generated method stub
		QueryWrapper<SaleOrderLine> lineQuery = new QueryWrapper<SaleOrderLine>();
		lineQuery.eq("sale_order_id", id);
		List<SaleOrderLine> lineList = saleOrderLineService.list(lineQuery);
		BigDecimal amountUntaxed = new BigDecimal(0);
		for (SaleOrderLine line : lineList) {
			BigDecimal qtyOrdered = line.getQtyOrdered();
			BigDecimal total = qtyOrdered.multiply(line.getPriceEntered());
			amountUntaxed = amountUntaxed.add(total);
		}
		return amountUntaxed;
	}

	@Override
	public BigDecimal calculateAmountTax(Long id) {
		// TODO Auto-generated method stub
		QueryWrapper<SaleOrderLine> lineQuery = new QueryWrapper<SaleOrderLine>();
		lineQuery.eq("sale_order_id", id);
		List<SaleOrderLine> lineList = saleOrderLineService.list(lineQuery);
		BigDecimal amountTax = new BigDecimal(0);
		for (SaleOrderLine line : lineList) {
			Long taxId = line.getAccountTaxId();
			BigDecimal qtyOrdered = line.getQtyOrdered();
			BigDecimal total = qtyOrdered.multiply(line.getPriceEntered());
			AccountTax accountTax = accountTaxService.getById(taxId);
			BigDecimal accountRate = accountTax.getRate().divide(new BigDecimal(100));
			amountTax = amountTax.add(total.multiply(accountRate));
		}
		return amountTax;
	}

	@Transactional
	public SaleOrder generateSaleOrder(Long saleQuotationId) {
		// TODO Auto-generated method stub
		SaleOrder saleOrder=new SaleOrder();
		SaleQuotation saleQuotation=saleQuotationService.getById(saleQuotationId);
		String docStatus=saleQuotation.getDocStatus();
		if(!"CO".equals(docStatus)) {
			throw new RuntimeException("请先完成单据");
		}
		saleOrder.setSaleQuotationId(saleQuotationId);
		Long docTypeId=irDocTypeService.getIrDocTypeIdByCode("saleorder");
		saleOrder.setIrDocTypeId(docTypeId);
		saleOrder.setDateOrdered(dateUtil.getSqlNowDatetime());
		saleOrder.setResPartnerId(saleQuotation.getResPartnerId());
		saleOrder.setDocStatus("DR");
		saleOrder.setAccountPaymentTermId(saleQuotation.getAccountPaymentTermId());
		saleOrder.setProductPricelistId(saleQuotation.getProductPricelistId());
		saleOrder.setDocumentNo(irSequenceService.getNextSequenceNo("saleorder"));
		insert(saleOrder);
		
		List<SaleQuotationLine> saleQuotationLineList=saleQuotationLineService.getLineListBySaleQuotationId(saleQuotationId);
		int lineNo=10;
		for(SaleQuotationLine saleQuotationLine:saleQuotationLineList) {
			SaleOrderLine saleOrderLine=new SaleOrderLine();
			saleOrderLine.setProductProductId(saleQuotationLine.getProductProductId());
			saleOrderLine.setQtyEntered(saleQuotationLine.getQtyEntered());
			saleOrderLine.setPriceEntered(saleQuotationLine.getPriceEntered());
			saleOrderLine.setUomUomId(saleQuotationLine.getUomUomId());
			saleOrderLine.setAccountTaxId(saleQuotationLine.getAccountTaxId());
			saleOrderLine.setSaleQuotationLineId(saleQuotationLine.getId());
			saleOrderLine.setSaleOrderId(saleOrder.getId());
			saleOrderLine.setLine(lineNo);
			lineNo+=10;
			saleOrderLineService.insert(saleOrderLine);
		}
		return saleOrder;
	}

	@Override
	@Transactional
	public void prepareIt(Long id) {
		// TODO Auto-generated method stub
		QueryWrapper<SaleOrderLine> lineQuery=new QueryWrapper<SaleOrderLine>();
		lineQuery.eq("sale_order_id", id);
		List<SaleOrderLine> lineList=saleOrderLineService.list(lineQuery);
		if(lineList==null ||lineList.size()==0 ) {
			throw new RuntimeException("没有行明细");
		}
	}

	@Override
	@Transactional
	public void approveIt(Long id) {
		// TODO Auto-generated method stub
		SaleOrder saleOrder=getById(id);
		saleOrder.setApproved(true);
		update(saleOrder);
	}

	@Override
	@Transactional
	public void rejectIt(Long id) {
		// TODO Auto-generated method stub
		SaleOrder saleOrder=getById(id);
		saleOrder.setApproved(false);
		update(saleOrder);
	}

	@Override
	@Transactional
	public void completeIt(Long id) {
		// TODO Auto-generated method stub
		SaleOrder saleOrder=getById(id);
		saleOrder.setDocStatus("CO");
		update(saleOrder);
		if(!saleOrder.getApproved()) {
			return;
		}
		QueryWrapper<SaleOrderLine> lineQuery=new QueryWrapper<SaleOrderLine>();
		lineQuery.eq("sale_order_id", id);
		List<SaleOrderLine> saleOrderLineList=saleOrderLineService.list(lineQuery);
		reserveStock(saleOrder,saleOrderLineList);
	}

	protected void reserveStock(SaleOrder saleOrder,List<SaleOrderLine> saleOrderLineList) {
		StockLocator stockLocator=stockLocatorService.getDefaultLocator(saleOrder.getStockWarehouseId());
		for(int i=0;i<saleOrderLineList.size();i++) {
			SaleOrderLine saleOrderLine=saleOrderLineList.get(i);
			saleOrderLine.setQtyReserved(saleOrderLine.getQtyOrdered());
			saleOrderLineService.update(saleOrderLine);
			stockStorageService.add(saleOrder.getStockWarehouseId(), stockLocator.getId(), saleOrderLine.getProductProductId(), 
					saleOrderLine.getProductAttrSetInstanceId(),new BigDecimal(0), saleOrderLine.getQtyOrdered(), new BigDecimal(0));
		}
	}
	
	@Override
	@Transactional
	public void setDocStatus(Long id, String docStatus) {
		// TODO Auto-generated method stub
		SaleOrder saleOrder=getById(id);
		saleOrder.setDocStatus(docStatus);
		update(saleOrder);
	}
}